﻿using System;
using System.Runtime.InteropServices;
using System.Text;

namespace CommonLibrary.Helper
{
    public class DllImportHelper
    {
        public const string User32 = "user32.dll";


        /// <summary>
        /// 检索指定窗口的父或所有者的句柄。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getparent
        /// </summary>
        /// <param name="hWnd">要检索其父窗口句柄的窗口的句柄。</param>
        /// <returns>如果窗口是子窗口，则返回值是父窗口的句柄。
        /// 如果窗口是具有 WS_POPUP 样式的顶级窗口，则返回值是所有者窗口的句柄。
        /// 如果函数失败，则返回值为 NULL。</returns>
        [DllImport(User32)]
        public static extern IntPtr GetParent(IntPtr hWnd);

        /// <summary>
        /// 更改指定子窗口的父窗口。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setparent
        /// </summary>
        /// <param name="hWndChild">子窗口的句柄</param>
        /// <param name="hWndNewParent">新父窗口的句柄</param>
        /// <returns>如果函数成功，则返回值是上一个父窗口的句柄。
        /// 如果函数失败，则返回值为 NULL。</returns>
        [DllImport(User32)]
        public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        /// <summary>
        /// 检索顶级窗口的句柄。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-findwindowa
        /// </summary>
        /// <param name="lpClassName">类名或</param>
        /// <param name="lpWindowName">窗口名称 (窗口的标题)。如果此参数为 NULL，则所有窗口名称都匹配。</param>
        /// <returns>如果函数成功，则返回值是具有指定类名和窗口名称的窗口的句柄。
        /// 如果函数失败，则返回值为 NULL。</returns>
        [DllImport(User32)]
        public static extern IntPtr FindWindowA(string lpClassName, string lpWindowName);

        /// <summary>
        /// 检索一个子窗口的句柄。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-findwindowexa
        /// </summary>
        /// <param name="hWndParent">要搜索其子窗口的父窗口的句柄。</param>
        /// <param name="hWndChildAfter">子窗口的句柄。 </param>
        /// <param name="lpszClass">类名</param>
        /// <param name="lpszWindow">窗口名称 (窗口的标题)。如果此参数为 NULL，则所有窗口名称都匹配。</param>
        /// <returns>如果函数成功，则返回值是具有指定类和窗口名称的窗口的句柄。
        /// 如果函数失败，则返回值为 NULL。</returns>
        [DllImport(User32)]
        public static extern IntPtr FindWindowExA(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);

        /// <summary>
        /// 检索指定窗口所属的类的名称。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getclassnamea
        /// </summary>
        /// <param name="hWnd">窗口的句柄，间接地是窗口所属的类。</param>
        /// <param name="lpClassName">类名字符串。</param>
        /// <param name="nMaxCount">lpClassName 缓冲区的长度（以字符为单位）</param>
        /// <returns>如果函数成功，则返回值是复制到缓冲区的字符数，不包括终止 null 字符。
        /// 如果函数失败，则返回值为零。
        /// 要获得更多的错误信息，请调用 GetLastError。</returns>
        [DllImport(User32)]
        public static extern IntPtr GetClassNameA(IntPtr hWnd, IntPtr lpClassName, int nMaxCount);

        /// <summary>
        /// 检索或设置其中一个系统范围的参数的值。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-systemparametersinfoa
        /// </summary>
        /// <param name="uAction">要检索或设置的系统范围参数</param>
        /// <param name="uParam">一个参数，其用法和格式取决于要查询或设置的系统参数</param>
        /// <param name="lpvParam">一个参数，其用法和格式取决于要查询或设置的系统参数</param>
        /// <param name="fuWinIni">如果正在设置系统参数，则指定是否要更新用户配置文件，
        /// 如果是，则指定是否将 WM_SETTINGCHANGE 消息广播到所有顶级窗口，以通知他们更改</param>
        /// <returns>如果函数成功，则返回值为非零值。</returns>
        [DllImport(User32)]
        public static extern int SystemParametersInfo(int uAction, int uParam, StringBuilder lpvParam, int fuWinIni);

        /// <summary>
        /// 将指定的消息发送到一个或多个窗口。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-sendmessage
        /// </summary>
        /// <param name="hWnd">窗口的句柄，其窗口过程将接收消息</param>
        /// <param name="Msg">要发送的消息</param>
        /// <param name="wParam">其他的消息特定信息</param>
        /// <param name="lParam">其他的消息特定信息</param>
        /// <returns>返回值指定消息处理的结果;这取决于发送的消息</returns>
        [DllImport(User32)]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

        /// <summary>
        /// 检索前台窗口的句柄(用户当前正在使用的窗口)。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getforegroundwindow
        /// </summary>
        /// <returns>返回值是前台窗口的句柄</returns>
        [DllImport(User32, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();

        /// <summary>
        /// 将创建指定窗口的线程引入前台并激活窗口。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setforegroundwindow
        /// </summary>
        /// <param name="hWnd">应激活并带到前台的窗口的句柄</param>
        /// <returns>如果将窗口带到前台，则返回值为非零值。
        /// 如果未将窗口带到前台，则返回值为零。</returns>
        [DllImport(User32, ExactSpelling = true)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        /// 检索或设置各种系统属性。参考 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-systemparametersinfoa
        /// 此函数还使应用程序能够更新用户配置文件，因此系统重启时将保留对系统的更改。
        /// 
        /// SPI_SETDESKWALLPAPER：设置桌面壁纸。pvParam参数必须指向一个包含位图文件名，并且以NULL（空）结束的字符串。
        /// </summary>
        /// <param name="uiAction">要检索或设置的系统范围参数。   SPI_SETDESKWALLPAPER</param>
        /// <param name="uiParam">其用法和格式取决于要查询或设置的系统参数。详见uiAction   0</param>
        /// <param name="pvParam">其用法和格式取决于要查询或设置的系统参数。详见uiAction   位图文件名/地址</param>
        /// <param name="fWinIni">如果正在设置系统参数，则指定是否要更新用户配置文件
        /// 如果是，则指定是否将 WM_SETTINGCHANGE 消息广播到所有顶级窗口，以通知他们更改。
        /// 如果不想更新用户配置文件或广播 WM_SETTINGCHANGE 消息，此参数可以为零，也可以是以下一个或多个值。
        /// SPIF_UPDATEINIFILE      将新的系统范围参数设置写入用户配置文件。
        /// SPIF_SENDCHANGE         在更新用户配置文件后广播 WM_SETTINGCHANGE 消息。
        /// SPIF_SENDWININICHANGE   与 SPIF_SENDCHANGE 相同。</param>
        /// <returns>如果函数成功，则返回值为非零值。
        /// 如果函数失败，则返回值为零。 </returns>
        [DllImport(User32)]
        public static extern IntPtr SystemParametersInfoA(int uiAction, int uiParam, string pvParam, int fWinIni);
    }
}
